﻿using Cms.Core.Application.IService.ModuleInfo;
using Cms.Core.Application.Service.ModuleInfo.Dto;
using Cms.Core.Data.Model;
using Cms.Core.Data.UnitOfWork;
using Cms.Core.Infrastructure.Common;
using Cms.Core.Infrastructure.Extension;
using Cms.Core.Infrastructure.Helps;
using Cms.Core.Infrastructure.Runtime.Session;
using Cms.Core.Infrastructure.Ui;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Linq;

namespace Cms.Core.Application.Service.ModuleInfo
{
    /// <summary>
    /// 模块API接口
    /// </summary>
    public class ModuleService : IModuleService
    {
        private readonly IRepository<SysModule> _sysModuleRepository = null;

        private readonly ICmsSession _session = null;
        private readonly Guid? _userId = null;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sysModuleRepository"></param>
        /// <param name="session"></param>
        public ModuleService(IRepository<SysModule> sysModuleRepository, ICmsSession session)
        {
            this._sysModuleRepository = sysModuleRepository;

            this._session = session;
            this._userId = session.UserId;
        }


        /// <summary>
        /// 添加模块API
        /// </summary>
        /// <param name="input"></param>
        /// <param name="checkModuleFunc"></param>
        /// <returns></returns>
        public async Task<OperationResult> AddModuleAsync(ModuleDto input, Func<string, string, Guid, Task> checkModuleFunc)
        {

            return await _sysModuleRepository.InsertAsync(input, async o =>
            {

                await checkModuleFunc.Invoke(o.Name, o.LinkUrl, o.Id);


            }, async (dto, r) => {

                //r.OrderSort = await MaxOrderSortAsync();
                r.ModifiedUserId = _userId;
                r.CreateUserId = _userId;
                r.OrderSort = await this.MaxOrderSortAsync(input.OrderSort);
                return r;
            });

        }

        /// <summary>
        /// 异步更新或者更新模块API
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<OperationResult> UpdateOrAddModuleAsync(ModuleDto input)
        {
            Func<string, string, Guid, Task> checkModuleFunc = async (name, linkUrl, id) =>
            {
                CheckModuleIsNullOrEmpty(name, linkUrl);
                await CheckModuleIsExistAsync(name, linkUrl, id);

            };

            if (input.Id == Guid.Empty)
            {
                return await this.AddModuleAsync(input, checkModuleFunc);
            }
            return await this.UpdateModuleAsync(input, checkModuleFunc);
        }

        /// <summary>
        /// 更新模块API异步
        /// </summary>
        /// <param name="input"></param>
        /// <param name="checkModuleFunc"></param>
        /// <returns></returns>
        public async Task<OperationResult> UpdateModuleAsync(ModuleDto input, Func<string, string, Guid, Task> checkModuleFunc)
        {

            return await _sysModuleRepository.UpdateNotQueryAsync(input, async (dto, Module) =>
            {
                await checkModuleFunc.Invoke(dto.Name, dto.LinkUrl, dto.Id);
            }, async (dto, r) => {

                r.ModifiedUserId = _userId;
                r.OrderSort = await this.MaxOrderSortAsync(input.OrderSort);
                return r;
            }, o => o.Name,
              o=>o.ParentId,
              o => o.LinkUrl,
              o => o.Description,
              o => o.Code,
              o => o.ModifiedTime,
              o => o.ModifiedUserId,
              o => o.IsEnabled,
              o=>o.Group,
               o => o.OrderSort);
        }

        /// <summary>
        /// 得到模块API分页信息
        /// </summary>
        /// <param name="pageRequestData">分页请求数据</param>
        /// <returns></returns>

        public async Task<PageResult> GetModulePageDataAsync(PageRequestData pageRequestData)
        {
            pageRequestData.NotNull(nameof(pageRequestData));
            var filter = FilterHelp.ToFilterExpression<SysModule>(pageRequestData.Filters);
            filter.NotNull(nameof(filter));

            var query = await _sysModuleRepository.QueryNotDelete.ToPageAsync(filter, pageRequestData, o => new {
                Id = o.Id,

                LinkUrl = o.LinkUrl,
                Name = o.Name,
                Code = o.Code,
                CreateTime = o.CreateTime,
                ModifiedTime = o.ModifiedTime,
                OrderSort = o.OrderSort,
                IsEnabled = o.IsEnabled,
                Group = o.Group,
                Description = o.Description
            });
            return query.ToPageResult();
        }


        /// <summary>
        /// 最大排序号
        /// </summary>
        /// <returns></returns>
        public async Task<int> MaxOrderSortAsync(int orderSort=0)
        {
            if (orderSort == 0)
            {
                int? maxOrderSort = await _sysModuleRepository.Entities.MaxAsync(o => (int?)o.OrderSort);
                return (maxOrderSort.HasValue ? maxOrderSort.Value + 1 : 0);
            }
            return orderSort;
        }
        /// <summary>
        /// 检查是否为空
        /// </summary>
        /// <param name="name"></param>
        /// <param name="linkUrl"></param>
        private void CheckModuleIsNullOrEmpty(string name, string linkUrl)
        {
            if (name.IsNullOrWhiteSpace())
            {
                throw new CustomException("模块API名不能为空!!");
            }

            if (linkUrl.IsNullOrWhiteSpace())
            {
                throw new CustomException("Api链接不能为空!!");
            }



        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="moduleName"></param>
        /// <param name="linkUrl"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        private async Task<bool> CheckModuleIsExistAsync(string moduleName, string linkUrl, Guid id)
        {
            var isExist = await _sysModuleRepository.Query(module => (module.Name == moduleName) && (module.Id != (id != Guid.Empty ? id : Guid.Empty))).AnyAsync();

            if (isExist)
            {
                throw new CustomException("此资源已存在！！！");
            }
            return isExist;
        }


        /// <summary>
        /// 异步软删除
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        public async  Task<OperationResult> SoftDeleteModuleAsync(Guid id) {
            return await _sysModuleRepository.SoftDeleteAsync(id);
        }



        /// <summary>
        ///得到所有模块转成下拉项
        /// </summary>
        public async Task<OperationResult> GetAllModuleToSelectItem()
        {
            var list = await _sysModuleRepository.QueryNotDelete.Where(o => o.IsEnabled == true).Select(o => new
            {

                Id = o.Id,
                Label = o.LinkUrl,
                Value = o.Name,
                GroupNmae = o.Group,

            }).ToListAsync();
         
            var groupNames=  list.Select(i => i.GroupNmae).Distinct();
            List<ModuleSelectItem> moduleSelectItems = new List<ModuleSelectItem>();

            foreach (var name in groupNames)
            {
                var groups = list.Where(o => o.GroupNmae == name).Select(o=>new ModuleSelectItem
                {
                    Id=o.Id.ToString(),
                    Label=o.Label,
                    Value=o.Value,
                }).ToList();
                ModuleSelectItem moduleSelectItem = new ModuleSelectItem();
                moduleSelectItem.Label = name;
                moduleSelectItem.Groups.AddRange(groups);
                moduleSelectItems.Add(moduleSelectItem);
            }
            return new OperationResult()
            {
                Type = OperationResultType.Success,
                Data = moduleSelectItems,
                Message = "查询成功",

            };
        }
    }

    public class ModuleSelectItem {

        public string Id { get; set; }

        public string Label { get; set; }

        public string Value { get; set; }

        public List<ModuleSelectItem> Groups { get; set; } = new List<ModuleSelectItem>();
    }


}
